#include "pch.h"
#include "FilePluginImpl.h"
#include "..\Common\Utility.h"
#include "..\FileTransfer\FileTransfer.h"

CFilePlugin::CFilePlugin()
{
	AssertInUIThread();
}

CFilePlugin::~CFilePlugin()
{
	AssertInUIThread();
}

void CFilePlugin::SetServer(LPCWSTR lpServerRoot)
{
	AssertInUIThread();

	if (!lpServerRoot || *lpServerRoot == 0)
		return;

	// Set the remote path, the lpRemotePath below are all relative to it
	m_strServerRoot = lpServerRoot;
	Util::FormatFilePath(m_strServerRoot);
}

bool CFilePlugin::VisitDir(LPCWSTR lpRemotePath, IDirVisitorPtr pCallback)
{
	AssertInThreadpool();
	assert(m_strServerRoot.size());

	if (m_strServerRoot.empty() || !lpRemotePath || !pCallback)
		return false;

	std::wstring strFileName = m_strServerRoot + lpRemotePath;
	Util::FormatFilePath(strFileName);
	strFileName += '*';

	bool bCanceled = false;
	bool bResult = Util::EnumDirectory(strFileName.c_str(), [pCallback, &bCanceled](FIND_DATA&& findData)
	{
		if (pCallback->IsCanceled())
		{
			bCanceled = true;
			return false;
		}

		LARGE_INTEGER liFileSize;
		liFileSize.LowPart = findData.nFileSizeLow;
		liFileSize.HighPart = findData.nFileSizeHigh;

		// Ordered callbacks in the thread pool
		AT::OrderedTask(pCallback, [pCallback](FileInfo&& fileInfo)
		{
			if (!pCallback->IsCanceled())
				pCallback->OnVisit(std::move(fileInfo));
		}, FileInfo{ findData.cFileName, liFileSize.QuadPart, findData.ftLastWriteTime, findData.dwFileAttributes });

		return true;
	});

	if (!bResult)
	{
		if (!bCanceled)
			LogError(L"EnumDirectory error: %s, Error=%d", strFileName, GetLastError());

		AT::OrderedTask(pCallback, &IDirVisitor::OnError, pCallback);
	}

	return true;
}

bool CFilePlugin::ReadFile(LPCWSTR lpRemotePath, IFileReaderPtr pCallback, INT64 nOffset, INT64 nLength)
{
	AssertInThreadpool();
	assert(m_strServerRoot.size());

	if (m_strServerRoot.empty() || !lpRemotePath || !pCallback)
		return false;

	// Combine the full path and give it to FileTransfer to read
	std::wstring strFileName = m_strServerRoot + lpRemotePath;
	return FT::GetFileTransfer()->ReadFile(strFileName.c_str(), std::move(pCallback), nOffset, nLength);
}
